package com.jerei.admin.base;

import com.jerei.plugin.api.IMenuDetailService;
import com.jerei.plugin.entity.WcmCommonAdminuser;
import com.jerei.plugin.entity.WcmCommonMenuDetail;
import com.jerei.plugin.exceptions.PluginNotInstallException;
import com.jerei.plugin.utils.Plugins;
import com.jerei.utils.UtilsCommon;
import com.jerei.web.utils.UtilsPluginManager;
import com.jerei.web.utils.UtilsWeb;
import com.jerei.web.utils.shiro.exceptions.ShowAuthCodeException;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.List;
import java.util.Random;

/**
 * Created by sunfeihu on 2016/10/21.
 */
@Controller
@RequestMapping(value = "/admin")
public class AdminHomeControl {


    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public String index(Model model) throws PluginNotInstallException {
        WcmCommonAdminuser adminuser = (WcmCommonAdminuser) SecurityUtils.getSubject().getPrincipal();
        IMenuDetailService iMenuDetailService = UtilsPluginManager.getExtension(IMenuDetailService.class, Plugins.COMMON_MENU);
        List<WcmCommonMenuDetail> rootMenuDetails = iMenuDetailService.getRootMenuDetail(adminuser);
        model.addAttribute("rootMenuDetails", rootMenuDetails);
        model.addAttribute("admin", adminuser);
        return "/admin/main/index";
    }

    @RequestMapping(value = "/main", method = RequestMethod.GET)
    public String main() {
        return "/admin/main/main";
    }

    @RequestMapping(value = "/left", method = RequestMethod.GET)
    public String left(Long id, Model model) throws PluginNotInstallException {
        if (null != id) {
            IMenuDetailService iMenuDetailService = UtilsPluginManager.getExtension(IMenuDetailService.class, Plugins.COMMON_MENU);
            WcmCommonAdminuser adminuser = (WcmCommonAdminuser) SecurityUtils.getSubject().getPrincipal();
            model.addAttribute("menuDetails", iMenuDetailService.getLeftMenuDetail(adminuser.getId(), id));
        } else {
            model.addAttribute("menuDetails", null);
        }
        return "/admin/main/left";
    }

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String loginForm(Model model, HttpServletRequest request) {
        WcmCommonAdminuser adminuser = (WcmCommonAdminuser) SecurityUtils.getSubject().getPrincipal();
        if (null != adminuser) {
            return "redirect:/admin/index";
        }
        model.addAttribute("admin", new WcmCommonAdminuser());
        return "/admin/main/login";
    }

    @RequestMapping(value = "/sort", method = RequestMethod.GET)
    public String sort() {
        return "/admin/main/sort";
    }

    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String login(@Valid WcmCommonAdminuser user, RedirectAttributes redirectAttributes, HttpServletRequest request) {
        String error = "";
        Subject subject = SecurityUtils.getSubject();
        try {
            if (null != subject.getSession().getAttribute("showAuthCode")) {
                Boolean showAuthCode = (Boolean) subject.getSession().getAttribute("showAuthCode");
                //如果是显示验证码，进行校验
                if (showAuthCode) {
                    String authCode = UtilsWeb.getString(request, "authCode");
                    String sessionAuthCode = UtilsCommon.getString(subject.getSession().getAttribute("sessionAuthCode"));
                    //如果输入验证码和session验证码不符
                    if (!authCode.equals(sessionAuthCode)) {
                        redirectAttributes.addFlashAttribute("message", "验证码输入错误");
                        return "redirect:/admin/login";
                    }
                }
            }
            UsernamePasswordToken token = new UsernamePasswordToken(user.getUsern(), user.getPassword());
            String rememberMe = UtilsWeb.getString(request, "rememberMe");
            if (null != rememberMe && "true".equals(rememberMe)) {
                token.setRememberMe(true);
            }
            subject.login(token);
        } catch (UnknownAccountException e) {
            error = "用户名/密码错误";
        } catch (ShowAuthCodeException e) {
            //如果是显示验证码异常，进行显示验证码
            error = "用户名/密码错误";
            subject.getSession().setAttribute("showAuthCode", true);
        } catch (IncorrectCredentialsException e) {
            error = "用户名/密码错误";
        } catch (ExcessiveAttemptsException e) {
            error = "登录失败多次，账户锁定10分钟";
        } catch (DisabledAccountException e) {
            error = "账户被禁用";
        } catch (AuthenticationException e) {
            error = "其他错误：" + e.getMessage();
        }
        if (error != null && !"".equals(error)) {// 出错了，返回登录页面
            redirectAttributes.addFlashAttribute("message", error);
            return "redirect:/admin/login";
        } else {// 登录成功
            return "redirect:/admin/index";
        }
    }

    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public String logout() throws IOException {
        //使用权限管理工具进行用户的退出，跳出登录，给出提示信息
        SecurityUtils.getSubject().logout();
        return null;
    }

    @RequestMapping(value = "/403", method = RequestMethod.GET)
    public String unauthorizedRole() {
        return "/admin/403";
    }

    @RequestMapping(value = "/main/plugins", method = RequestMethod.GET)
    public String pluginsList() {
        return "/admin/main/plugins";
    }

    @RequestMapping(value = "/authCode", method = RequestMethod.GET)
    public void getAuthCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
        Subject subject = SecurityUtils.getSubject();
        int width = 80;
        int height = 35;
        Random random = new Random();
        //设置response头信息
        //禁止缓存
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        //生成缓冲区image类
        BufferedImage image = new BufferedImage(width, height, 1);
        //产生image类的Graphics用于绘制操作
        Graphics g = image.getGraphics();
        //Graphics类的样式
        g.setColor(this.getRandColor(200, 250));
        g.setFont(new Font("Times New Roman", 0, 28));
        g.fillRect(0, 0, width, height);
        //绘制干扰线
        for (int i = 0; i < 40; i++) {
            g.setColor(this.getRandColor(130, 200));
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int x1 = random.nextInt(12);
            int y1 = random.nextInt(12);
            g.drawLine(x, y, x + x1, y + y1);
        }

        //绘制字符
        String strCode = "";
        for (int i = 0; i < 4; i++) {
            String rand = String.valueOf(random.nextInt(10));
            strCode = strCode + rand;
            g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
            g.drawString(rand, 13 * i + 6, 28);
        }
        //将字符保存到session中用于前端的验证
        subject.getSession().setAttribute("sessionAuthCode", strCode);
        g.dispose();
        ImageIO.write(image, "JPEG", response.getOutputStream());
        response.getOutputStream().flush();
    }

    private Color getRandColor(int fc, int bc) {
        Random random = new Random();
        if (fc > 255)
            fc = 255;
        if (bc > 255)
            bc = 255;
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    }

}